package fr.nts.application.novadmin.service.impl;

import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.google.common.collect.Maps;

import fr.nts.application.novadmin.database.dao.NovadminEmployeeCompletDao;
import fr.nts.application.novadmin.database.dao.NovadminEmployeeSimpleDao;
import fr.nts.application.novadmin.database.model.employe.NovadminEmployeComplet;
import fr.nts.application.novadmin.database.model.employe.NovadminEmployeSimple;
import fr.nts.application.novadmin.service.NovadminUserService;
import fr.nts.framework.core.commun.enumeration.Encoding;
import fr.nts.framework.core.commun.tool.PasswordUtil;
import fr.nts.framework.core.commun.tool.PasswordUtil.Difficulty;
import fr.nts.framework.core.service.MailSender;
import fr.nts.framework.core.service.TemplateMaker;
import fr.nts.framework.core.task.SimpleTask;
import fr.nts.framework.core.task.SimpleTaskManager;
import fr.nts.framework.database.jpa.dao.SecurityUserDao;
import fr.nts.framework.database.jpa.model.security.SecurityUser;
import fr.nts.framework.database.jpa.transaction.JPAReadonlyTransaction;

/**
 * Implémentation du service {@link NovadminUserService}
 * 
 * @author sco
 * @version 1.0.0
 */
@Component("novadminUserService")
public class NovadminUserServiceImpl implements NovadminUserService{

	private static final Logger log = LoggerFactory.getLogger(NovadminUserServiceImpl.class);
	
	@Resource
	private SecurityUserDao securityUserDao; 
	
	@Resource
	private NovadminEmployeeSimpleDao novadminEmployeeSimpleDao;
	
	@Resource
	private NovadminEmployeeCompletDao novadminEmployeeCompletDao;
	
	@Resource(name = "novadminMailSender")
	private MailSender mailSender;
	
	@Resource(name = "novadminTemplateMaker")
	private TemplateMaker templateMaker;

	@Resource(name = "novadminThreadTaskManager")
	private SimpleTaskManager threadTaskManager; 
	
	@Value("${nts.novadmin.service.resetpassword.from:administrator@novadmin.fr}")
	private String emailFrom;
	
	@Value("${nts.novadmin.service.resetpassword.subject:NOVADMIN - Réinitialisation password}")
	private String emailSubject;
	
	private final static String NAME = "name";
	private final static String FIRSTNAME = "firstname";
	private final static String PASSWORD = "password";
	
	private final static String RESET_PASSWORD_TEMPLATE = "/template/reset_password.vm";
	
	
	/*
	 * (non-Javadoc)
	 * @see fr.nts.application.novadmin.service.NovadminUserService#loadNovadminEmployee(java.lang.String)
	 */
	@Override
	@JPAReadonlyTransaction
	public NovadminEmployeSimple loadNovadminEmployee(final String username){	
		return novadminEmployeeSimpleDao.findByLogin(username);
	}

	
	/*
	 * (non-Javadoc)
	 * @see fr.nts.application.novadmin.service.NovadminUserService#loadNovadminEmployeeComplet(java.lang.String)
	 */
	@Override
	@JPAReadonlyTransaction
	public NovadminEmployeComplet loadNovadminEmployeeComplet(final String username){	
		return novadminEmployeeCompletDao.findByLogin(username);
	}


	/*
	 * (non-Javadoc)
	 * @see fr.nts.application.novadmin.service.NovadminUserService#resetEmployeePassword(java.lang.String)
	 */
	@Override
	public void resetEmployeePassword(final String username){
		
		// Mise à jour de l'utilisateur
		SecurityUser securityUser = securityUserDao.findByLogin(username);
		
		// Utilisateur inconu
		if(securityUser == null){
			return;
		}
		
		String newPassword = PasswordUtil.generateNewPassword(Difficulty.HARD_PASSWORD);
		securityUser.setPassword(newPassword);
		
		securityUserDao.update(securityUser);
		
		// Préparation de l'email
		NovadminEmployeSimple employee = novadminEmployeeSimpleDao.findByLogin(username);
		Map<String, Object> values = Maps.newHashMap();
		values.put(NAME, 
				   employee.getNom());
		values.put(FIRSTNAME, 
				   employee.getPrenom());
		values.put(PASSWORD, 
				   newPassword);
		
		String emailContent = templateMaker.generateContent(values, 
				                                            RESET_PASSWORD_TEMPLATE, 
				                                            Encoding.UTF8);
		
		// Envoi de l'email
		log.debug("Lancement de la tâche de l'envoi du mail de réinitialisation du password");
		threadTaskManager.launchNewTaskInBackground(new SendResetPasswordTask(emailContent, 
				                                                              employee.getEmailPerso()));
	}
	
	
	/**
	 * Tâche d'envoi de l'email
	 */
	private class SendResetPasswordTask implements SimpleTask<Boolean>{

		/**
		 * Contenu du mail
		 */
		private String emailContent;
		
		/**
		 * Email de destination
		 */
		private String emailDest;
		
		/**
		 * Le résultat de la tâche
		 */
		private boolean result = true;
		
		
		public SendResetPasswordTask(String emailContent,
				                     String emailDest){
			this.emailContent = emailContent;
			this.emailDest = emailDest;
		}
		
		
		/*
		 * (non-Javadoc)
		 * @see java.lang.Runnable#run()
		 */
		@Override
		public void run(){
			if(log.isDebugEnabled()){
				log.debug("On va envoyer le mail [{}] à [{}] ==> {}",
						  new Object[]{emailSubject, emailDest, emailContent});
			}else{
				log.info("On va envoyer un mail de réinitialisation de password à [{}]", emailDest);
			}
			
			if(!mailSender.sendHTMLEmail(emailFrom, 
					                     emailDest, 
					                     emailContent, 
					                     emailSubject)){
				result = false;
				log.debug("Echec dans l'envoi de l'email.");
			}else{
				log.debug("Réussite de l'envoi du mail de réinitialisation du password");
			}
		}

		
		/*
		 * (non-Javadoc)
		 * @see fr.nts.framework.core.task.SimpleTask#getResult()
		 */
		@Override
		public Boolean getResult(){
			return result;
		}
	}
}